import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog, QLineEdit, QPushButton, QVBoxLayout, QLabel
from PyQt5 import QtCore, QtGui, QtWidgets
import numpy as np
from functools import partial
import RPi.GPIO as GPIO


class Ui_MainWindow(object):
    def __init__(self, bsize):
        super(Ui_MainWindow, self).__init__()
        # 设置柜子的尺寸，并创建状态数组
        self.h = bsize[0]
        self.w = bsize[1]
        self.box_num = self.h * self.w
        # [0, 0, 0, 0, 0, 0, 0, 0, 0], 0=>空闲，1=>使用中
        self.box_status = np.zeros(self.box_num, dtype=np.uint8)
        self.initGPIO()
        self.input_book_name = ''
        self.search_book_name = ''
        self.book_names_in_box = [''] * self.box_num

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(440, 420)
        self.mainWin = MainWindow
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(110, 30, 500, 71))
        font = QtGui.QFont()
        font.setPointSize(25)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.layoutWidget.setGeometry(QtCore.QRect(90, 140, 261, 151))
        self.layoutWidget.setObjectName("layoutWidget")
        self.gridLayout = QtWidgets.QGridLayout(self.layoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")

        self.checkBoxs = []
        for i in range(self.box_num):
            self.checkBoxs.append(QtWidgets.QCheckBox(self.layoutWidget))
            self.checkBoxs[i].setObjectName(f'checkBox_{i+1}')
            self.checkBoxs[i].clicked.connect(partial(self.change_box_status, i))
        self.gridLayout.addWidget(self.checkBoxs[0], 0, 0, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[1], 0, 1, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[2], 0, 2, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[3], 1, 0, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[4], 1, 1, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[5], 1, 2, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[6], 2, 0, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[7], 2, 1, 1, 1)
        self.gridLayout.addWidget(self.checkBoxs[8], 2, 2, 1, 1)
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(40, 320, 361, 61))
        self.widget.setObjectName("widget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label_2 = QtWidgets.QLabel(self.widget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.lineEdit = QtWidgets.QLineEdit(self.widget)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.pushButton = QtWidgets.QPushButton(self.widget)
        self.pushButton.clicked.connect(lambda: self.show_dialog_to_search_book(self.lineEdit.text()))
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout.addWidget(self.pushButton)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.label.setText(_translate("MainWindow", "“找都快”智能书架"))
        for i in range(self.box_num):
            self.checkBoxs[i].setText(_translate("MainWindow", "空闲"))
        self.label_2.setText(_translate("MainWindow", "书籍名："))
        self.pushButton.setText(_translate("MainWindow", "搜索"))

    def initGPIO(self):
        GPIO.setmode(GPIO.BCM)  # BCM引脚编号模式
        GPIO.setwarnings(False)
        for gled, rled in led_io:
            GPIO.setup(gled, GPIO.OUT)
            GPIO.setup(rled, GPIO.OUT)
            GPIO.output(gled, GPIO.HIGH)
            GPIO.output(rled, GPIO.LOW)

    def change_box_status(self, index):  # status: 1(占用中)/0(空闲)
        if self.checkBoxs[index].isChecked():
            self.input_book_name = ''
            self.show_dialog_to_store_book(index)
            if self.input_book_name != '':
                self.checkBoxs[index].setText('占用中')
                self.box_status[index] = 1
            else:
                self.checkBoxs[index].setChecked(False)
                self.box_status[index] = 0
        else:
            self.checkBoxs[index].setText('空闲')
            self.box_status[index] = 0
            self.book_names_in_box[index] = ''
        change_led_state(self.box_status)
        print(self.box_status)
        print(self.book_names_in_box)

    def show_dialog_to_store_book(self, index):
        dialog = QDialog(self.mainWin)
        dialog.setWindowTitle('存储书籍')
        dialog.resize(200, 150)
        layout = QVBoxLayout()
        label = QLabel('请输入书籍名：')
        layout.addWidget(label)
        lineEdit = QLineEdit()
        layout.addWidget(lineEdit)
        button = QPushButton('确认')
        button.clicked.connect(lambda: self.get_input_content(index, lineEdit.text(), dialog))
        layout.addWidget(button)
        dialog.setLayout(layout)
        dialog.exec_()

    def show_dialog_to_search_book(self, book_name):
        index = -1
        for i in range(len(self.book_names_in_box)):
            if self.book_names_in_box[i] == book_name:
                index = i
                break
        dialog = QDialog(self.mainWin)
        dialog.setWindowTitle('查找书籍')
        dialog.resize(200, 150)
        # centralwidget = QtWidgets.QWidget(self.mainWin)
        if index != -1:
            label = QLabel(f'书籍《{book_name}》的位置是：\n\t({(index + 1) // self.w + 1}, {(index + 1) % self.w})', dialog)
        else:
            label = QLabel('从书架上未找到相应书籍', dialog)
        label.setGeometry(QtCore.QRect(20, 20, 200, 50))
        label.show()
        dialog.exec_()
    def get_input_content(self, index, content, dialog):
        self.input_book_name = content
        self.book_names_in_box[index] = content
        # print(self.book_names_in_box)
        dialog.close()

"""
# 将树莓派读取到的串口状态保存到本地
def write_data_to_local(box_status):
    print(box_status)
    np.savetxt(txt_path, box_status.astype(np.uint8))
def read_data_from_local():
    return np.loadtxt(txt_path).astype(np.uint8)
def btn_is_pressed(read_serial_fun, times=30, least_times=30):  # 防止按键抖动
    io = []
    for i in range(times):
        io.append(read_serial_fun())
    offset = np.abs(np.min(io))
    mapped_array = io + offset
    counts = np.bincount(mapped_array)
    # 获取出现次数最多的元素和次数
    most_common_element = np.argmax(counts) - offset
    most_common_count = np.max(counts)
    print(io)
    if most_common_count >= least_times:
        return most_common_element
    return -1
"""

def change_led_state(box_status):
    for i in range(len(box_status)):
        if box_status[i] == green_led:
            GPIO.output(led_io[i][0], GPIO.HIGH)
            GPIO.output(led_io[i][1], GPIO.LOW)
        elif box_status[i] == red_led:
            GPIO.output(led_io[i][0], GPIO.LOW)
            GPIO.output(led_io[i][1], GPIO.HIGH)

green_led = 0
red_led = 1
# parameters
win_size = (440, 420)  # 窗口尺寸
box_size = (3, 3)  # 书柜的尺寸
led_io = [[27, 2], [10, 9], [11, 5], [4, 3], [22, 17], [13, 6], [26, 19], [16, 12], [21, 20]]  # led 0~8 [green, red]

if __name__ == "__main__":
    app = QApplication(sys.argv)
    mainWindow = QMainWindow()
    ui = Ui_MainWindow(box_size)
    ui.setupUi(mainWindow)
    mainWindow.setFixedSize(win_size[0], win_size[1])
    mainWindow.show()
    app.aboutToQuit.connect(mainWindow.closeEvent)  # 绑定关闭事件
    sys.exit(app.exec_())
